using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using WeiboSharp.Models;
using WeiboSharp.Web;

namespace WeiboSharp
{
    public class WeiboRequest
    {
        public WebMethod Method { get; set; }
        public IAuthenticator Credentials { get; set; }
        public string Path { get; set; }
        public int Timeout { get; set; }
        public List<Parameter> Parameters { get; private set; }
        public List<FileParameter> Files { get; private set; }

        public WeiboRequest()
        {
            Method = WebMethod.Get;
            Parameters = new List<Parameter>();
            Files = new List<FileParameter>();
        }

        public void AddParameter(Parameter parameter)
        {
            Parameters.Add(parameter);
        }

        private void AddParameter(string name, string value, ParameterType type)
        {
            Parameters.Add(new Parameter(name, value) { Type = type });
        }

        public void AddUrlSegment(string name, string value)
        {
            AddParameter(name, value, ParameterType.UrlSegment);
        }

        public void AddHeader(string name, string value)
        {
            AddParameter(name, value, ParameterType.HttpHeader);
        }

        public void AddParameter(string name, string value)
        {
            AddParameter(name, value, ParameterType.GetOrPost);
        }

        //public void AddField(string name, string value)
        //{
        //    AddParameter(name, value, ParameterType.RequestBody);
        //}

        public void AddFile(string name, string path)
        {
            AddFile(new FileParameter
            {
                Name = name,
                FileName = System.IO.Path.GetFileName(path),
                Writer = s =>
                {
                    using (var file = new StreamReader(path))
                    {
                        file.BaseStream.CopyTo(s);
                    }
                }
            });
        }

        /// <summary>
        /// Adds the bytes to the Files collection with the specified file name
        /// </summary>
        /// <param name="name">The parameter name to use in the request</param>
        /// <param name="bytes">The file data</param>
        /// <param name="fileName">The file name to use for the uploaded file</param>
        /// <returns>This request</returns>
        public void AddFile(string name, byte[] bytes, string fileName)
        {
            AddFile(FileParameter.Create(name, bytes, fileName));
        }

        /// <summary>
        /// Adds the bytes to the Files collection with the specified file name and content type
        /// </summary>
        /// <param name="name">The parameter name to use in the request</param>
        /// <param name="bytes">The file data</param>
        /// <param name="fileName">The file name to use for the uploaded file</param>
        /// <param name="contentType">The MIME type of the file to upload</param>
        /// <returns>This request</returns>
        public void AddFile(string name, byte[] bytes, string fileName, string contentType)
        {
            AddFile(FileParameter.Create(name, bytes, fileName, contentType));
        }

        /// <summary>
        /// Adds the bytes to the Files collection with the specified file name and content type
        /// </summary>
        /// <param name="name">The parameter name to use in the request</param>
        /// <param name="writer">A function that writes directly to the stream.  Should NOT close the stream.</param>
        /// <param name="fileName">The file name to use for the uploaded file</param>
        /// <returns>This request</returns>
        public void AddFile(string name, Action<Stream> writer, string fileName)
        {
            AddFile(name, writer, fileName, null);
        }

        /// <summary>
        /// Adds the bytes to the Files collection with the specified file name and content type
        /// </summary>
        /// <param name="name">The parameter name to use in the request</param>
        /// <param name="writer">A function that writes directly to the stream.  Should NOT close the stream.</param>
        /// <param name="fileName">The file name to use for the uploaded file</param>
        /// <param name="contentType">The MIME type of the file to upload</param>
        /// <returns>This request</returns>
        public void AddFile(string name, Action<Stream> writer, string fileName, string contentType)
        {
            AddFile(new FileParameter { Name = name, Writer = writer, FileName = fileName, ContentType = contentType });
        }

        private void AddFile(FileParameter file)
        {
            Files.Add(file);
        }

        private int _attempts;
        /// <summary>
        /// How many attempts were made to send this Request?
        /// </summary>
        /// <remarks>
        /// This Number is incremented each time the RestClient sends the request.
        /// Useful when using Asynchronous Execution with Callbacks
        /// </remarks>
        public int Attempts
        {
            get { return _attempts; }
        }

        /// <summary>
        /// Internal Method so that RestClient can increase the number of attempts
        /// </summary>
        internal void IncreaseNumAttempts()
        {
            _attempts++;
        }


    }
}
